/*
 * @Author: your name
 * @Date: 2021-03-31 09:20:20
 * @LastEditTime: 2021-04-19 11:21:05
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \tower_defense\assets\scripts\game_scene\tower\electricity_tower.ts
 */

import { ElectricityTowerParams } from "../../game_data/tower_data/electricity_tower_params";
import { UG } from "../../modules/ugame";
import { FrameAnim } from "../../common/frame_anim";
import { ElectricityBullet } from "../bullet/electricity_bullet";

const { ccclass, property } = cc._decorator;

// 自定义类
@ccclass("electricity_tower_skin")
class electricity_tower_skin {
    @property(cc.SpriteFrame)   // 塔资源
    public tower_anim: Array<cc.SpriteFrame> = [];
}

@ccclass
export class ElectricityTower extends cc.Component {

    @property(cc.Integer)  // 塔等级
    public tower_level: number = 1;
    @property(cc.Integer)
    public shoot_anim_sample: number = 10;    // 动画帧速率
    @property(cc.Node)
    public anim_node: cc.Node = null;
    @property(cc.Graphics)  // 画笔
    public graphics: cc.Graphics = null;

    @property(cc.Prefab)    // 子弹预制体
    public electricity_bullet_pre: cc.Prefab = null;

    @property({             // 塔每个等级的皮肤
        type: electricity_tower_skin,
    })
    public level_tower_skin = [];

    public electricity_tower_frame_anim: FrameAnim = null;    // 保存自定义动画组件

    public bullet_root_node: cc.Node = null;    // 子弹存放节点
    public is_debug: boolean = true;           // 是否开启塔攻击范围绘制
    public tower_center_pos: cc.Vec2 = cc.v2();     // 塔中心坐标
    public tower_center_pos_in_tower_panel: cc.Vec2 = null; // tower_panel坐标系下的塔中心节点

    start() {
        this.scheduleOnce(this.electricity_tower_ai.bind(this), 0.1);
    }

    onLoad() {
        // this.is_debug = true;

        this.bullet_root_node = cc.find('Canvas/tower_panel/bullet_root');

        // 获取塔中心坐标
        this.tower_center_pos = this.get_tower_center_pos();

        // 开启debug
        // this._draw_tower_debug();

        // 绑定自定义动画组件
        this.electricity_tower_frame_anim = this.anim_node.addComponent(FrameAnim);
        this.electricity_tower_frame_anim.sprite_com = this.anim_node.getComponent(cc.Sprite);
        this.electricity_tower_frame_anim.anim_com = this.anim_node.getComponent(cc.Animation);
    }

    // 获取塔等级
    public get_tower_level(): any {
        // return this.tower_level;
        return true;
    }

    // 升级塔
    public upgrade_tower(): any {
        // 电塔只有一个等级          
        cc.log("已经最高级");
        return true;
    }

    // 根据等级设置塔图片
    private _set_tower_skin_by_level(): void {
        let sprite: cc.Sprite = this.anim_node.getComponent(cc.Sprite);
        sprite.spriteFrame = this.level_tower_skin[this.tower_level - 1].tower_anim[0];
    }

    // 获取塔中心位置
    public get_tower_center_pos(): cc.Vec2 {
        let center_pos: cc.Vec2 = this.node.getPosition();

        let _a: cc.Vec2 = this.node.parent.convertToWorldSpaceAR(this.tower_center_pos);   // 转为世界坐标
        let _b: cc.Vec2 = this.node.parent.parent.convertToNodeSpaceAR(_a);

        this.tower_center_pos_in_tower_panel = _b;

        // this.graphics.circle(_b.x, _b.y, 5);
        // this.graphics.fill();

        return center_pos;
    }

    // 绘制塔攻击范围
    private _draw_tower_debug(): void {
        if (!this.is_debug) {
            return;
        }
        // 先清除
        this.graphics.clear();
        // 搜索半径
        let search_r: number = ElectricityTowerParams[this.tower_level - 1].search_R;
        // 绘制
        const _b: cc.Vec2 = this.tower_center_pos_in_tower_panel;
        this.graphics.circle(_b.x, _b.y, search_r);
        this.graphics.stroke();
    }

    // ===================================== 塔行为 ========================================

    // 发射
    private _shoot_electricity_bullet(level: number, enemy_world_pos: cc.Vec2, enemy: cc.Node): void {
        // 炮塔只有1级
        if (this.tower_level > 1) {
            return;
        }

        const start_pos_arr: Array<cc.Vec2> = [cc.v2(10, 30)];
        let start_world_pos: cc.Vec2 = this.anim_node.convertToWorldSpaceAR(start_pos_arr[this.tower_level - 1]);

        // 发射炮弹
        let electricity_bullet_node: cc.Node = cc.instantiate(this.electricity_bullet_pre);
        electricity_bullet_node.parent = this.bullet_root_node;
        let electricity_bullet_com: ElectricityBullet = electricity_bullet_node.getComponent(ElectricityBullet);
        electricity_bullet_com.bullet_level = level;
        electricity_bullet_com.shoot(level, start_world_pos, enemy_world_pos, enemy);
    }

    // 射击动画
    public shoot_anim(enemy_world_pos: cc.Vec2, enemy: cc.Node): void {
        this.electricity_tower_frame_anim.sprite_frame_arr = this.level_tower_skin[this.tower_level - 1].tower_anim;
        this.shoot_anim_sample = 10;
        this.electricity_tower_frame_anim.sample = this.shoot_anim_sample;

        // 播放一次蓄力动画
        this.electricity_tower_frame_anim.play_once(() => {
            // cc.log('蓄力动画结束');
            // 播放完成，恢复塔图片
            this._set_tower_skin_by_level();
        });

        // 发射子弹
        this._shoot_electricity_bullet(this.tower_level, enemy_world_pos, enemy);
    }

    // 塔AI
    public electricity_tower_ai(): void {
        if (!this.tower_center_pos) {
            this.tower_center_pos = this.get_tower_center_pos();
        }
        // 获取塔中心位置
        let center_pos: cc.Vec2 = this.tower_center_pos;
        // 搜索半径
        let search_r = ElectricityTowerParams[this.tower_level - 1].search_R;
        // 扫描时间间隔
        let time: number = 0.1;
        // 攻击敌人
        let enemy: cc.Node = UG.search_enemy(center_pos, search_r);
        if (enemy) {
            // cc.log('找到敌人');
            let _enemy_world_pos: cc.Vec2 = enemy.parent.convertToWorldSpaceAR(cc.v2(enemy.x, enemy.y));   // 再敌人的父节点中，把敌人转为世界坐标
            // 播放射击动画
            this.shoot_anim(_enemy_world_pos, enemy);
            // 要根据 动画时间计算  33帧动画
            // time = 1 / this.shoot_anim_sample * this.level_tower_skin[this.tower_level - 1].tower_anim.length - 0.1;
            time = 2.9;
        }
        this.scheduleOnce(this.electricity_tower_ai.bind(this), time);
    }
}
